BASIC PYTHON FOR RESEARCHERS

by Megat Harun Al Rashid bin Megat Ahmad
last updated: April 14, 2016


9. Scientific Python by Examples

In general, Scientific Python package or better known as SciPy is a Python-based software for mathematics, science, and engineering. It includes some of the libraries that have been discussed before, i.e. **sympy**, **numpy**, **matplotlib** and **pandas**, as well as a library named **scipy**.

The scopes and applications of SciPy libraries are quite large to be covered in just one tutorial. Henceforth, only examples on specific subjects those the author has experienced doing the computations will be presented here.


9.1 Curve Fitting

Here we will see the fitting of a curve or actually a peak/peaks of an X-ray diffraction data of a composite material (the data are courtesy of Mr. Mohd Reusmazran, a colleague of mine).

Here we will use the functions available in **pandas** library as well as **scipy**, **numpy** and **matplotlib**.


In [1]:
# Importing function from pandas
from pandas import read_excel

# Reading excel file and extract data from specific sheet
from_excel = read_excel('Tutorial9/XRD 30_50PLLA2.xlsx','PLLA 50kGy')

In [2]:
# Checking the content
from_excel.head()


Out[2]:
No. Pos. [°2Th.] Iobs [cts] Icalc [cts] Iback [cts] CT [s] ESD D spacings
0 NaN NaN NaN NaN NaN NaN NaN NaN
1 1 5.0167 1185.002 NaN NaN 19.4424 NaN 17.60077
2 2 5.0497 1159.331 NaN NaN 19.4424 NaN 17.48582
3 3 5.0827 1166.800 NaN NaN 19.4424 NaN 17.37236
4 4 5.1157 1167.002 NaN NaN 19.4424 NaN 17.26037

In [3]:
# Extracting the array values
PLLA50kgy = from_excel.values
PLLA50kgy


Out[3]:
array([[             nan,              nan,              nan, ...,
                     nan,              nan,              nan],
       [  1.00000000e+00,   5.01670000e+00,   1.18500200e+03, ...,
          1.94424000e+01,              nan,   1.76007700e+01],
       [  2.00000000e+00,   5.04970000e+00,   1.15933100e+03, ...,
          1.94424000e+01,              nan,   1.74858200e+01],
       ..., 
       [  2.27000000e+03,   7.98937000e+01,   1.39655800e+02, ...,
          1.94424000e+01,              nan,   1.19970000e+00],
       [  2.27100000e+03,   7.99267000e+01,   1.48066600e+02, ...,
          1.94424000e+01,              nan,   1.19929000e+00],
       [  2.27200000e+03,   7.99597000e+01,   1.33235000e+02, ...,
          1.94424000e+01,              nan,   1.19887000e+00]])

In [4]:
# Checking by selecting columns of interest
PLLA50kgy[1:,1:3]


Out[4]:
array([[    5.0167,  1185.002 ],
       [    5.0497,  1159.331 ],
       [    5.0827,  1166.8   ],
       ..., 
       [   79.8937,   139.6558],
       [   79.9267,   148.0666],
       [   79.9597,   133.235 ]])

In [5]:
# Transposing the selected columns of interest
XRDPLLA50kgy = PLLA50kgy[1:,1:3].T
XRDPLLA50kgy


Out[5]:
array([[    5.0167,     5.0497,     5.0827, ...,    79.8937,    79.9267,
           79.9597],
       [ 1185.002 ,  1159.331 ,  1166.8   , ...,   139.6558,   148.0666,
          133.235 ]])

In [6]:
# It is now easy to simply plot and see the diffraction pattern
%matplotlib inline

import numpy as np
import matplotlib.pyplot as plt

plt.plot(XRDPLLA50kgy[0],XRDPLLA50kgy[1])
plt.xlabel(r'2$\theta$')
plt.ylabel('counts')
plt.show()



In [7]:
# Looking into peak of interest (from 5 to 30 of x-axis)

plt.figure(figsize=(4, 3))

# Checking the amount of data points
plt.plot(XRDPLLA50kgy[0],XRDPLLA50kgy[1], 'x')
#plt.plot(XRDPLLA50kgy[0],XRDPLLA50kgy[1])
plt.xlim(5,28.1167)
plt.ylim(0,2000)
plt.xlabel(r'2$\theta$')
plt.ylabel('counts')
plt.show()


The background fitting is necessary in order to fit this peak with a gaussian function. Thus the fitting will include an equation the sum the gaussian function and background. It is better make a guess first on the parameters values for this equation before performing fitting optimization.


In [8]:
# Initial plot and fitting parameters guessing (Gaussian)

# Select the plot range of interest
sudutE = XRDPLLA50kgy[0][5:700]
keamatanE = XRDPLLA50kgy[1][5:700]

a1 = 870; a2 = 1450; 
b1 = 16; b2 = -9.5; 
c1 = 3.5; c2 = 12; 

# Manual fitting with Gaussian
x1_val = np.linspace(5,28,695) # Creating x-values
y2_val = a2*np.exp(-(x1_val-b2)**2/(2*c2**2))+400 # Gaussian background

y1_val = a1*np.exp(-(x1_val-b1)**2/(2*c1**2)) # Gaussian peak

plt.figure(figsize=(14, 3))

plt.plot(sudutE,keamatanE,'g') # Plot data
plt.plot(x1_val,y2_val,'b') # Plot background
plt.plot(x1_val,y1_val,'r') # Plot peak
plt.plot(x1_val,y1_val+y2_val,'r--') # Plot peak plus background


plt.title('Manual')
plt.ylabel('Intensity')
plt.xlabel(r'2$\theta$')
plt.xlim


Out[8]:
<function matplotlib.pyplot.xlim>

In [9]:
# Fitting curve using scipy curve_fit module

import numpy as np
from scipy.optimize import curve_fit

def fitGaussian(xvar,af,bf,cf,df,ae,be,ce):
    return af*np.exp(-(xvar-bf)**2/(2*cf**2))+ae*np.exp(-(xvar-be)**2/(2*ce**2))+df

# it return best fit values for parameters
# pass the function name, x data, y data, initial value of parameters (in list)
popt, pcov = curve_fit(fitGaussian, sudutE, keamatanE,\
                       [870,16,3.5,400,1450,-9.5,12],sigma =keamatanE)

print popt # fitting parameters obtained
print pcov


[ 1072.05940764    15.8123433      5.11920972   357.29574148   705.67540757
     3.89386998     2.72509348]
[[  2.67901636e+01  -3.18351364e-02   1.19159659e-01  -1.92204131e+01
   -5.81903477e+01   5.74467033e-01  -3.53511435e-01]
 [ -3.18351364e-02   1.18678437e-03  -1.08345791e-03   5.31457484e-02
    9.78946280e-01  -8.17481393e-03   5.25544137e-03]
 [  1.19159659e-01  -1.08345791e-03   2.45656673e-03  -2.28303817e-01
   -9.92293510e-01   8.78331789e-03  -5.92753648e-03]
 [ -1.92204131e+01   5.31457484e-02  -2.28303817e-01   2.84966751e+01
    5.55374376e+01  -5.53442773e-01   3.81627559e-01]
 [ -5.81903477e+01   9.78946280e-01  -9.92293510e-01   5.55374376e+01
    2.75448549e+03  -2.09360338e+01   1.02772412e+01]
 [  5.74467033e-01  -8.17481393e-03   8.78331789e-03  -5.53442773e-01
   -2.09360338e+01   1.66077607e-01  -8.42743832e-02]
 [ -3.53511435e-01   5.25544137e-03  -5.92753648e-03   3.81627559e-01
    1.02772412e+01  -8.42743832e-02   4.55548104e-02]]

In [10]:
# Plotting the best fit using the fitting parameters

y_val = popt[0]*np.exp(-(sudutE-popt[1])**2/(2*popt[2]**2))+popt[4]*\
np.exp(-(sudutE-popt[5])**2/(2*popt[6]**2))+popt[3]

plt.plot(sudutE,keamatanE,'g',label = "Data PLLA50kgy")
plt.plot(sudutE,y_val,'r-', ls='--', label="Exp Fit")
plt.title('Data Fitting')
plt.ylabel('Intensity')
plt.xlabel(r'2$\theta$')
plt.legend(loc = 'upper right')
plt.ylim(300,1800)
plt.xlim(5,28.1167)
plt.savefig('Tutorial9/Fitting_PLLA50kgy.jpeg')


It is now easy to obtain the peak properties, for instance, area under the peak (minus the background).


In [11]:
# Area under the peak using trapezoidal method
np.trapz(popt[0]*np.exp(-(sudutE-popt[1])**2/(2*popt[2]**2)), x=sudutE)


Out[11]:
13382.69751417479

Now let us try to fit all peaks the x-ray diffraction data.


In [12]:
def fitGaussianAll(xvar,af,bf,cf,df,ae,be,ce,ag,bg,cg,\
                ag1,bg1,cg1,ag2,bg2,cg2,ag3,bg3,cg3,ag4,bg4,cg4,ag5,bg5,cg5):
    return af*np.exp(-(xvar-bf)**2/(2*cf**2))+\
    ae*np.exp(-(xvar-be)**2/(2*ce**2))+\
    ag*np.exp(-(xvar-bg)**2/(2*cg**2))+\
    ag1*np.exp(-(xvar-bg1)**2/(2*cg1**2))+\
    ag2*np.exp(-(xvar-bg2)**2/(2*cg2**2))+\
    ag3*np.exp(-(xvar-bg3)**2/(2*cg3**2))+\
    ag4*np.exp(-(xvar-bg4)**2/(2*cg4**2))+\
    ag5*np.exp(-(xvar-bg5)**2/(2*cg5**2))+\
    df

a1 = 870; a2 = 1450; a3 = 7300; a4 = 300; a5 = 380; a6 = 300; a7 = 600; a8 = 500
b1 = 16; b2 = -9.5; b3 = 29.5; b4 = 36.1; b5 = 39.5; b6 = 43.3; b7 = 47.7; b8 = 48.7
c1 = 3.5; c2 = 12; c3 = 0.02; c4 = 0.02; c5 = 0.02; c6 = 0.02; c7 = 0.02; c8 = 0.02
df1 = 357.3
# it return best fit values for parameters
# pass the function name, x array, y array, initial value of parameters (in list)
poptAll, pcovAll = curve_fit(fitGaussianAll, XRDPLLA50kgy[0], XRDPLLA50kgy[1],\
                       [a1,b1,c1,df1,a2,b2,c2,a3,b3,c3,a4,b4,c4,a5,b5,c5,a6,b6,c6,a7,b7,c7,a8,b8,c8],\
                       sigma =XRDPLLA50kgy[1])

print poptAll
print pcovAll


[  7.41766757e+02   1.66972386e+01   3.62735173e+00   1.37967705e+02
   1.41014705e+03  -2.67768776e+01   3.22230320e+01   5.69622656e+03
   2.94977836e+01   9.20249955e-02   2.32517165e+02   3.60555006e+01
   9.45220702e-02   3.16374200e+02   3.95102290e+01   1.03280071e-01
   3.30202433e+02   4.32764020e+01   9.94215531e-02   5.94636026e+02
   4.76417344e+01   1.40283596e-01   4.25845156e+02   4.86358882e+01
   1.33955260e-01]
[[  1.12720367e+02  -4.27407682e-02  -1.44076718e-01  -2.01405107e+00
    7.41610770e+01  -3.85338648e+00   1.52838129e+00  -1.19923508e+01
   -1.54770775e-05   3.28027739e-04   1.12131557e+00  -4.44690349e-05
    1.35833196e-03   3.55439801e-01  -3.46972760e-05   4.29433979e-04
   -8.77850724e-02  -2.50770200e-05  -1.13937701e-04  -1.12543233e-01
   -2.62659636e-05  -3.91274644e-04  -2.39598554e-01  -2.55617811e-05
   -5.51589038e-04]
 [ -4.27407682e-02   3.14042977e-03  -1.09796194e-03  -5.94921518e-03
    2.10256523e+00  -4.93464526e-02   1.25919730e-02  -8.72914142e-03
    1.26322876e-08   2.40692956e-07   4.28570438e-03   3.86727721e-08
    5.19687592e-06   3.16104089e-03  -1.02740360e-08   3.83790309e-06
    1.99378861e-03  -5.55089647e-08   2.55797027e-06   3.11125951e-04
   -4.75434045e-08   9.70582949e-07   4.27073900e-04  -6.91840226e-08
    9.43671183e-07]
 [ -1.44076718e-01  -1.09796194e-03   3.31961945e-03  -1.45160571e-02
   -1.59335668e-01  -1.75386374e-02   9.44060851e-03  -1.00133766e-01
    3.91330705e-08   2.76186068e-06   1.47654990e-02  -4.51177999e-07
    1.78937154e-05   6.10857351e-03  -3.35436573e-07   7.40162829e-06
    1.16338217e-03  -2.51028215e-07   1.48544211e-06  -5.46255969e-04
   -2.20284636e-07  -1.97557546e-06  -1.33848174e-03  -2.26144639e-07
   -3.10522912e-06]
 [ -2.01405107e+00  -5.94921518e-03  -1.45160571e-02   1.75960268e+00
   -9.50861545e+01   3.14440467e+00  -1.10189955e+00   2.47580474e+00
    1.89233212e-06  -6.79444787e-05  -1.35277845e-01   1.73248992e-05
   -1.63221254e-04   8.06334666e-02   1.42429528e-05   9.91310800e-05
    2.00537253e-01   8.64720088e-06   2.58123214e-04   8.48066291e-02
    1.09851474e-05   2.86771170e-04   1.63363901e-01   9.00684024e-06
    3.73137393e-04]
 [  7.41610770e+01   2.10256523e+00  -1.59335668e-01  -9.50861545e+01
    1.08628394e+04  -3.16171118e+02   9.82043921e+01  -2.62576927e+02
   -1.48713699e-04   7.20440037e-03   3.34715199e+01  -1.14975629e-03
    4.05356154e-02   1.12451081e+01  -1.06908193e-03   1.35728861e-02
   -3.25070191e+00  -8.77550013e-04  -4.22642082e-03  -4.15211020e+00
   -1.01452515e-03  -1.45034212e-02  -8.94585812e+00  -1.01215812e-03
   -2.06274668e-02]
 [ -3.85338648e+00  -4.93464526e-02  -1.75386374e-02   3.14440467e+00
   -3.16171118e+02   9.57870028e+00  -3.05956596e+00   8.98568318e+00
    5.06765308e-06  -2.46594316e-04  -1.06722745e+00   4.17287014e-05
   -1.29230196e-03  -3.12898367e-01   3.73399092e-05  -3.77099726e-04
    1.65563248e-01   2.92911087e-05   2.14358408e-04   1.53292517e-01
    3.41926825e-05   5.32361768e-04   3.23833994e-01   3.35233654e-05
    7.45599017e-04]
 [  1.52838129e+00   1.25919730e-02   9.44060851e-03  -1.10189955e+00
    9.82043921e+01  -3.05956596e+00   1.00028935e+00  -2.90737330e+00
   -1.72566449e-06   7.97919841e-05   3.09096252e-01  -1.48441794e-05
    3.74151191e-04   6.30611513e-02  -1.30044888e-05   7.55474309e-05
   -8.96016100e-02  -9.69272023e-06  -1.15672067e-04  -6.00770044e-02
   -1.17228371e-05  -2.07093331e-04  -1.23633245e-01  -1.11881473e-05
   -2.84105437e-04]
 [ -1.19923508e+01  -8.72914142e-03  -1.00133766e-01   2.47580474e+00
   -2.62576927e+02   8.98568318e+00  -2.90737330e+00   6.36187397e+04
    4.09973306e-02  -3.29514478e-01  -2.99763763e+00   5.38043181e-05
   -3.63386256e-03  -1.57393189e+00   4.49614354e-05  -1.90953068e-03
   -6.76356327e-01   4.26270645e-05  -8.67336391e-04  -3.28111658e-02
    3.33755493e-05  -7.82285540e-05   9.11832643e-03   3.89777188e-05
    3.29914404e-05]
 [ -1.54770775e-05   1.26322876e-08   3.91330705e-08   1.89233212e-06
   -1.48713699e-04   5.06765308e-06  -1.72566449e-06   4.09973306e-02
    4.53267471e-06  -3.34610264e-07  -7.50215826e-07   3.21339845e-11
   -9.08465952e-10  -2.01425811e-07   2.70453078e-11  -2.42622447e-10
    1.31914312e-07   2.02036060e-11   1.70564297e-10   1.09598118e-07
    2.33420635e-11   3.79530844e-10   2.29319198e-07   2.26511208e-11
    5.27599355e-10]
 [  3.28027739e-04   2.40692956e-07   2.76186068e-06  -6.79444787e-05
    7.20440037e-03  -2.46594316e-04   7.97919841e-05  -3.29514478e-01
   -3.34610264e-07   3.15421004e-06   8.23209266e-05  -1.47724580e-09
    9.97929188e-08   4.32271420e-05  -1.23436057e-09   5.24442190e-08
    1.85810715e-05  -1.17034014e-09   2.38277757e-08   9.04103111e-07
   -9.16097563e-10   2.15870074e-09  -2.44390025e-07  -1.06997927e-09
   -8.92211862e-10]
 [  1.12131557e+00   4.28570438e-03   1.47654990e-02  -1.35277845e-01
    3.34715199e+01  -1.06722745e+00   3.09096252e-01  -2.99763763e+00
   -7.50215826e-07   8.23209266e-05   7.11557939e+02  -3.22437232e-03
   -1.60444277e-01   3.58105664e-01  -3.95250821e-06   4.34965992e-04
    2.17685602e-01  -5.43229391e-06   2.79553259e-04   4.04390042e-02
   -2.12580909e-06   1.30607362e-04   6.39132882e-02  -3.82401520e-06
    1.43842671e-04]
 [ -4.44690349e-05   3.86727721e-08  -4.51177999e-07   1.73248992e-05
   -1.14975629e-03   4.17287014e-05  -1.48441794e-05   5.38043181e-05
    3.21339845e-11  -1.47724580e-09  -3.22437232e-03   1.12721831e-04
    8.90970293e-07  -1.02238927e-07   2.58704841e-10  -1.03314294e-10
    2.56615585e-06   1.78115509e-10   3.30733963e-09   1.35293092e-06
    2.28748003e-10   4.63331345e-09   2.71654588e-06   2.12540950e-10
    6.23270601e-09]
 [  1.35833196e-03   5.19687592e-06   1.78937154e-05  -1.63221254e-04
    4.05356154e-02  -1.29230196e-03   3.74151191e-04  -3.63386256e-03
   -9.08465952e-10   9.97929188e-08  -1.60444277e-01   8.90970293e-07
    1.00197920e-04   4.34433134e-04  -4.78147010e-09   5.27676769e-07
    2.64222659e-04  -6.58069652e-09   3.39317102e-07   4.91312466e-05
   -2.56647159e-09   1.58695434e-07   7.76827043e-05  -4.62742982e-09
    1.74838531e-07]
 [  3.55439801e-01   3.16104089e-03   6.10857351e-03   8.06334666e-02
    1.12451081e+01  -3.12898367e-01   6.30611513e-02  -1.57393189e+00
   -2.01425811e-07   4.32271420e-05   3.58105664e-01  -1.02238927e-07
    4.34433134e-04   7.22647520e+02  -6.34493999e-03  -1.22990181e-01
    1.80619491e-01  -2.00134337e-06   2.32076923e-04   4.26487535e-02
    8.80419511e-07   1.40497251e-04   7.34315055e-02  -4.82861432e-07
    1.66508106e-04]
 [ -3.46972760e-05  -1.02740360e-08  -3.35436573e-07   1.42429528e-05
   -1.06908193e-03   3.73399092e-05  -1.30044888e-05   4.49614354e-05
    2.70453078e-11  -1.23436057e-09  -3.95250821e-06   2.58704841e-10
   -4.78147010e-09  -6.34493999e-03   6.50494568e-05   1.53393302e-06
    2.14183502e-06   1.52828631e-10   2.76089765e-09   1.14886870e-06
    1.98230443e-10   3.93918589e-09   2.31527303e-06   1.85833404e-10
    5.31428103e-09]
 [  4.29433979e-04   3.83790309e-06   7.40162829e-06   9.91310800e-05
    1.35728861e-02  -3.77099726e-04   7.55474309e-05  -1.90953068e-03
   -2.42622447e-10   5.24442190e-08   4.34965992e-04  -1.03314294e-10
    5.27676769e-07  -1.22990181e-01   1.53393302e-06   5.53858519e-05
    2.19726669e-04  -2.41989631e-09   2.82326272e-07   5.19372042e-05
    1.08706157e-09   1.71109391e-07   8.94529793e-05  -5.70963145e-10
    2.02842870e-07]
 [ -8.77850725e-02   1.99378861e-03   1.16338217e-03   2.00537253e-01
   -3.25070191e+00   1.65563248e-01  -8.96016100e-02  -6.76356328e-01
    1.31914311e-07   1.85810715e-05   2.17685602e-01   2.56615585e-06
    2.64222659e-04   1.80619491e-01   2.14183502e-06   2.19726669e-04
    6.70769561e+02  -5.51097254e-03  -1.01454096e-01   4.26467536e-02
    2.70419277e-06   1.42112916e-04   7.69568808e-02   1.60058928e-06
    1.75180960e-04]
 [ -2.50770200e-05  -5.55089647e-08  -2.51028215e-07   8.64720088e-06
   -8.77550013e-04   2.92911087e-05  -9.69272023e-06   4.26270645e-05
    2.02036060e-11  -1.17034014e-09  -5.43229391e-06   1.78115509e-10
   -6.58069652e-09  -2.00134337e-06   1.52828631e-10  -2.41989631e-09
   -5.51097254e-03   5.00960777e-05   1.12043404e-06   4.91694153e-07
    1.36152500e-10   1.73251400e-09   1.09080209e-06   1.38825759e-10
    2.52089706e-09]
 [ -1.13937702e-04   2.55797027e-06   1.48544211e-06   2.58123214e-04
   -4.22642082e-03   2.14358408e-04  -1.15672067e-04  -8.67336391e-04
    1.70564298e-10   2.38277757e-08   2.79553259e-04   3.30733963e-09
    3.39317102e-07   2.32076923e-04   2.76089765e-09   2.82326272e-07
   -1.01454096e-01   1.12043404e-06   4.08482798e-05   5.48465596e-05
    3.48350013e-09   1.82771925e-07   9.89828591e-05   2.06512933e-09
    2.25322027e-07]
 [ -1.12543233e-01   3.11125951e-04  -5.46255969e-04   8.48066291e-02
   -4.15211020e+00   1.53292517e-01  -6.00770044e-02  -3.28111706e-02
    1.09598114e-07   9.04103172e-07   4.04390042e-02   1.35293092e-06
    4.91312466e-05   4.26487535e-02   1.14886870e-06   5.19372042e-05
    4.26467536e-02   4.91694153e-07   5.48465596e-05   9.23280394e+02
    6.20477005e-03  -9.99670467e-02  -2.85796525e-01  -4.03841306e-05
    1.82228591e-04]
 [ -2.62659636e-05  -4.75434045e-08  -2.20284636e-07   1.09851474e-05
   -1.01452515e-03   3.41926825e-05  -1.17228371e-05   3.33755492e-05
    2.33420635e-11  -9.16097562e-10  -2.12580909e-06   2.28748003e-10
   -2.56647159e-09   8.80419511e-07   1.98230443e-10   1.08706157e-09
    2.70419277e-06   1.36152500e-10   3.48350013e-09   6.20477005e-03
    2.73153092e-05  -9.85089543e-07   2.93292680e-05   3.44055279e-09
   -4.83803719e-09]
 [ -3.91274644e-04   9.70582949e-07  -1.97557546e-06   2.86771170e-04
   -1.45034212e-02   5.32361768e-04  -2.07093331e-04  -7.82285522e-05
    3.79530844e-10   2.15870073e-09   1.30607362e-04   4.63331345e-09
    1.58695434e-07   1.40497251e-04   3.93918589e-09   1.71109391e-07
    1.42112916e-04   1.73251400e-09   1.82771925e-07  -9.99670467e-02
   -9.85089543e-07   2.35053036e-05   1.67226604e-04   1.40620545e-08
    1.61781195e-07]
 [ -2.39598554e-01   4.27073900e-04  -1.33848174e-03   1.63363901e-01
   -8.94585812e+00   3.23833994e-01  -1.23633245e-01   9.11832188e-03
    2.29319195e-07  -2.44389998e-07   6.39132882e-02   2.71654588e-06
    7.76827043e-05   7.34315055e-02   2.31527303e-06   8.94529793e-05
    7.69568808e-02   1.09080209e-06   9.89828591e-05  -2.85796525e-01
    2.93292680e-05   1.67226604e-04   6.06622386e+02  -7.77270438e-03
   -9.19660624e-02]
 [ -2.55617811e-05  -6.91840227e-08  -2.26144639e-07   9.00684024e-06
   -1.01215812e-03   3.35233654e-05  -1.11881473e-05   3.89777188e-05
    2.26511209e-11  -1.06997927e-09  -3.82401520e-06   2.12540950e-10
   -4.62742982e-09  -4.82861432e-07   1.85833404e-10  -5.70963145e-10
    1.60058928e-06   1.38825759e-10   2.06512933e-09  -4.03841306e-05
    3.44055279e-09   1.40620545e-08  -7.77270438e-03   3.77508624e-05
    1.73862643e-06]
 [ -5.51589038e-04   9.43671183e-07  -3.10522912e-06   3.73137393e-04
   -2.06274668e-02   7.45599017e-04  -2.84105437e-04   3.29914398e-05
    5.27599356e-10  -8.92211868e-10   1.43842671e-04   6.23270601e-09
    1.74838531e-07   1.66508106e-04   5.31428103e-09   2.02842870e-07
    1.75180960e-04   2.52089706e-09   2.25322027e-07   1.82228591e-04
   -4.83803719e-09   1.61781195e-07  -9.19660624e-02   1.73862643e-06
    3.23691261e-05]]

In [13]:
plt.figure(figsize=(14, 6))

y_back = poptAll[4]*np.exp(-(XRDPLLA50kgy[0]-poptAll[5])**2/(2*poptAll[6]**2))+poptAll[3]
y_p1 = poptAll[0]*np.exp(-(XRDPLLA50kgy[0]-poptAll[1])**2/(2*poptAll[2]**2))
y_p2 = poptAll[7]*np.exp(-(XRDPLLA50kgy[0]-poptAll[8])**2/(2*poptAll[9]**2))
y_p3 = poptAll[10]*np.exp(-(XRDPLLA50kgy[0]-poptAll[11])**2/(2*poptAll[12]**2))
y_p4 = poptAll[13]*np.exp(-(XRDPLLA50kgy[0]-poptAll[14])**2/(2*poptAll[15]**2))
y_p5 = poptAll[16]*np.exp(-(XRDPLLA50kgy[0]-poptAll[17])**2/(2*poptAll[18]**2))
y_p6 = poptAll[19]*np.exp(-(XRDPLLA50kgy[0]-poptAll[20])**2/(2*poptAll[21]**2))
y_p7 = poptAll[22]*np.exp(-(XRDPLLA50kgy[0]-poptAll[23])**2/(2*poptAll[24]**2))

y_all = y_p1+y_p2+y_p3+y_p4+y_p5+y_p6+y_p7+y_back

plt.plot(XRDPLLA50kgy[0],XRDPLLA50kgy[1],'g')
plt.plot(XRDPLLA50kgy[0],y_back,'b')
plt.plot(XRDPLLA50kgy[0],y_p1,'r')
plt.plot(XRDPLLA50kgy[0],y_p2,'r')
plt.plot(XRDPLLA50kgy[0],y_p3,'r')
plt.plot(XRDPLLA50kgy[0],y_p4,'r')
plt.plot(XRDPLLA50kgy[0],y_p5,'r')
plt.plot(XRDPLLA50kgy[0],y_p6,'r')
plt.plot(XRDPLLA50kgy[0],y_p7,'r')

plt.plot(XRDPLLA50kgy[0],y_all,'r--')

plt.title('Manual')
plt.ylabel('Intensity')
plt.xlabel(r'2$\theta$')


Out[13]:
<matplotlib.text.Text at 0x7fb965f69ed0>

The optimization routine used above was done according to Levensberg-Marquadt algorithm which is the default method. Other methods that can be used are Trust Region Reflective and Dogbox algorithms.


9.2 Simple Image Processing

This image processing example is about the investigation of internal nanostructures of ceramic particles from a Transmission Electron Microscope (TEM) image. This is part of research reported in Mater. Lett., 62(15) (2008) 2339-2342.

Here we will use the functions available in **scipy** library as well as **numpy** and **matplotlib**.


In [14]:
# Importing function from the scipy library
from scipy import misc

# Passing the image file as array to variable nanostr
nanostr = misc.imread('Tutorial9/06S11-13.TIF')

In [15]:
# Showing the image in grayscale

%matplotlib inline
import matplotlib.pyplot as plt

plt.imshow(nanostr, cmap=plt.cm.gray)


Out[15]:
<matplotlib.image.AxesImage at 0x7fb960ae8250>

In [16]:
# Checking the shape of the array
nanostr.shape


Out[16]:
(1112, 1376)

The image can be enlarged to inspect the details. The ratio of the pixels (or arrays)can give the exact ratio of the image when enlarging it.


In [17]:
plt.figure(figsize=(10,10*nanostr.shape[0]/nanostr.shape[1]))

plt.imshow(nanostr, cmap=plt.cm.gray)


Out[17]:
<matplotlib.image.AxesImage at 0x7fb960d360d0>

In order to remove the label below the image, it is better to know the exact pixel position of the boundary (here this is done for the $y$-axis)


In [18]:
# Checking the array boundary for the label
plt.imshow(nanostr[1000:1050,:50],cmap=plt.cm.gray)


Out[18]:
<matplotlib.image.AxesImage at 0x7fb965cede50>

The $y$-boundary for the label starts at about 1030 (as the image was extracted starting at pixel 1000).


In [19]:
# The image without label
plt.imshow(nanostr[:1030],cmap=plt.cm.gray)


Out[19]:
<matplotlib.image.AxesImage at 0x7fb965f69110>

It is possible to extract the parametric length of a pixel from the scale bar in the label. This can be used later to estimate the size of the nanostructures inside the particles.


In [20]:
# Extracting the scale bar image
plt.imshow(nanostr[1030:,1076:1076+290],cmap=plt.cm.gray)


Out[20]:
<matplotlib.image.AxesImage at 0x7fb965f39b50>

In [21]:
nanostr[1030:,1076:1076+290].shape


Out[21]:
(82, 290)

In the above the parametric length of a pixel (in nm) is:


In [22]:
pixSiz = 500/290.0
pixSiz, 'nm'


Out[22]:
(1.7241379310344827, 'nm')

The new area of the selected image without label can be passed to a new array.


In [23]:
nstr = nanostr[:1030]

Certain parts of the image, for instance, can be selected for further inspection.


In [24]:
# First, checking the shape of the new image
nstr.shape


Out[24]:
(1030, 1376)

In [25]:
# Selecting new area of interest
# and tinkering with values of its pixels
import numpy as np

square = np.zeros(nstr.shape)
square[275:641,400:776]=100

In [26]:
# Plotting the image by highlighting the new area of interest
plt.plot([400,400],[275,641],'b',linewidth=1)
plt.plot([776,776],[275,641],'b',linewidth=1)
plt.plot([400,776],[275,275],'b',linewidth=1)
plt.plot([400,776],[641,641],'b',linewidth=1)

plt.imshow(nstr+square,cmap=plt.cm.gray)


Out[26]:
<matplotlib.image.AxesImage at 0x7fb960a09d90>

Applying a false color analysis of the image provide a rich and detail information on the nanostructures of the particle.


In [27]:
plt.imshow(np.log(nstr[275:641,400:776]),cmap=plt.cm.nipy_spectral_r)
plt.colorbar()


Out[27]:
<matplotlib.colorbar.Colorbar at 0x7fb96007ab10>

The pixel values are in log scale thus the colorbar indicates that the values of interest is in the range of 4.3 to 5.2.

Sometimes a contour image can provide further information on the region of interest. The example below shows the contour image of the sample with modified pixel intensity of the original image and indicates the next selected image area as one that can provide details on the nanostructures.


In [28]:
plt.imshow((nstr[275:641,400:776]*0)+100, cmap=plt.cm.gray)
plt.contour(nstr[275:641,400:776])
plt.colorbar()


Out[28]:
<matplotlib.colorbar.Colorbar at 0x7fb95ad458d0>

Based on the contour plot above, an area is selected for further investigation.


In [29]:
# Selecting different region with different false color scheme
plt.plot([100,100],[1,75],'r',linewidth=2)
plt.plot([200,200],[1,75],'r',linewidth=2)
plt.plot([100,200],[1,1],'r',linewidth=2)
plt.plot([100,200],[75,75],'r',linewidth=2)

plt.imshow(np.log(nstr[275:641,400:776]), cmap=plt.cm.BrBG, vmin=4.3, vmax=5.2)
plt.colorbar()


Out[29]:
<matplotlib.colorbar.Colorbar at 0x7fb95abe00d0>

Displaying the new selected image:


In [30]:
plt.imshow(np.log(nstr[275:641,400:776][0:75,100:200]),cmap=plt.cm.gist_heat)


Out[30]:
<matplotlib.image.AxesImage at 0x7fb95ab2f5d0>

In [31]:
# An image of a bar showing the measurement of the size
plt.plot([9.4,11.9],[9.6,12.5],'g',linewidth=7) 
plt.imshow(np.log(nstr[275:641,400:776][0:75,100:200][50:70,20:40]),cmap=plt.cm.PuOr, \
           interpolation='bicubic')


Out[31]:
<matplotlib.image.AxesImage at 0x7fb95ab66e50>

Approximating the size of the nanostructures using value from scale bar in the original image.


In [32]:
print "The size of the nanostructures is %.2f nm." % \
(np.sqrt((11.9-9.4)**2 + (12.5-9.6)**2)*pixSiz)


The size of the nanostructures is 6.60 nm.

In [33]:
from scipy import ndimage

In [34]:
im=nstr[275:641,400:776]

im = ndimage.gaussian_filter(im, 1)

sx = ndimage.sobel(im, axis=0, mode='constant')
sy = ndimage.sobel(im, axis=1, mode='constant')
sob = np.hypot(sx, sy)

plt.figure(figsize=(16, 5))

plt.subplot(141)
plt.imshow(im, cmap=plt.cm.gray)
plt.axis('off')
plt.title('square', fontsize=20)

plt.subplot(142)
plt.imshow(sx)
plt.axis('off')
plt.title('Sobel (x direction)', fontsize=20)

plt.subplot(143)
plt.imshow(sob)
plt.axis('off')
plt.title('Sobel filter', fontsize=20)

im = im + 0.07*np.random.random(im.shape)

sx = ndimage.sobel(im, axis=0, mode='constant')
sy = ndimage.sobel(im, axis=1, mode='constant')
sob = np.hypot(sx, sy)

plt.subplot(144)
plt.imshow(sob)
plt.axis('off')
plt.title('Sobel for noisy image', fontsize=20)



plt.subplots_adjust(wspace=0.02, hspace=0.02, top=1, bottom=0, left=0, right=0.9)

plt.show()



In [35]:
ext_nstr = (nstr[275:641,400:776]<225)*(nstr[275:641,400:776]>100)*nstr[275:641,400:776]

In [36]:
plt.imshow(ext_nstr)


Out[36]:
<matplotlib.image.AxesImage at 0x7fb959fc44d0>